=begin pod :kind("Type") :subkind("class") :category("composite")

=TITLE class Array

=SUBTITLE Sequence of itemized values

    class Array is List {}

An C<Array> is a L<List|/type/List> which forces all its elements to be
scalar containers, which means you can assign to array elements.

C<Array> implements C<Positional> and as such provides support for
L<subscripts|/language/subscripts>.

B<Note> from version 6.d, C<.raku> (C<.perl> before version 2019.11) can be
called on multi-dimensional arrays.

If you want to declare an C<Array> of a specific type, you can do so using
several different ways:

=for code
my @foo of Int = 33,44;        # [33 44]
my @bar is Array[Int] = 33,44; # [33 44]

The second example, which parameterizes a type, is only available from Rakudo
2019.03.

=head1 Methods

=head2 method gist

Exactly the same as L«C<List.gist>|/type/List#method_gist»,
except using square brackets for surrounding delimiters.

=head2 method pop

Defined as:

    method pop(Array:D:) is nodal

Removes and returns the last item from the array.  Fails if the array is empty.

Like many C<Array> methods, method C<pop> may be called via the corresponding
L<subroutine|/language/independent-routines#sub_pop>. For example:

    my @foo = <a b>; # a b
    @foo.pop;        # b
    pop @foo;        # a
    pop @foo;
    CATCH { default { put .^name, ': ', .Str } };
    # OUTPUT: «X::Cannot::Empty: Cannot pop from an empty Array␤»

=head2 method push

Defined as:

    multi method push(Array:D: **@values is raw --> Array:D)
    multi method push(Array:D: \value --> Array:D)
    multi method push(Array:D: Slip \values --> Array:D)

Adds the provided value or values to the end of the array, and returns the
modified array. If any argument is a C<Slip>, method C<push> will add the values
produced by the argument's L<iterator|/routine/iterator>. It throws if the
invocant array or a C<Slip> L<is lazy|/routine/is-lazy>.

Example:

    my @foo = <a b c>;
    @foo.push: 'd';
    say @foo;                   # OUTPUT: «[a b c d]␤»

Note that C<push> does not attempt to flatten its argument list.  If you pass
an array or list as the thing to push, it becomes one additional element:

    my @a = <a b c>;
    my @b = <d e f>;
    @a.push: @b;
    say @a.elems;               # OUTPUT: «4␤»
    say @a[3].join;             # OUTPUT: «def␤»

Multiple values are added to the array only if you supply them as separate
arguments or in a L<slip|/type/Slip>:

   my @a = '1';
   say @a.push: 'a', 'b';       # OUTPUT: «[1 a b]␤»
   my @c = <E F>;
   say @a.push: @c.Slip;        # OUTPUT: «[1 a b E F]␤»

See L<method append|/type/Array#method_append> if you want to append multiple
values that are produced by a single non-slipping C<Iterable>.

=head2 method append

Defined as

    multi method append(Array:D: **@values is raw --> Array:D)
    multi method append(Array:D: \arg --> Array:D)

Adds the provided values to the end of the array and returns the modified array,
or throws if the invocant array or an argument that requires flattening L<is
lazy|/routine/is-lazy>.

In contrast with L<method push|/type/Array#method_push>, method C<append>
adheres to the L<single argument rule|/language/functions#Slurpy_conventions>
and is probably best thought of as:

    multi method append(Array:D: +values --> Array:D)

This means that if you pass a B<single> argument that is a
non-L<itemized|/language/mop#VAR> C<Iterable>, C<append> will try to flatten it.

For example:

    my @a = <a b c>;
    my @b = <d e f>;
    @a.append: @b;
    say @a.elems;               # OUTPUT: «6␤»
    say @a;                     # OUTPUT: «[a b c d e f]␤»

=head2 method elems

Defined as:

    method elems(Array:D: --> Int:D)

Returns the number of elements in the invocant. Throws C<X::Cannot::Lazy>
exception if the invocant L<is lazy|/routine/is-lazy>. For shaped arrays,
returns the outer dimension; see L<shape|/routine/shape> if you need information for
all dimensions.

    say [<foo bar ber>] .elems; # OUTPUT: «3␤»
    say (my @a[42;3;70]).elems; # OUTPUT: «42␤»

    try [-∞...∞].elems;
    say $!.^name;               # OUTPUT: «X::Cannot::Lazy␤»

=head2 method clone

Defined as:

    method clone(Array:D: --> Array:D)

Clones the original C<Array>. Modifications of elements in the clone
are not propagated to the original and vice-versa:

    my @a = <a b c>; my @b = @a.clone;
    @b[1] = 42; @a.push: 72;
    say @b; # OUTPUT: «[a 42 c]␤»
    say @a; # OUTPUT: «[a b c 72]␤»

However, note that the reifier I<is> shared between the two Arrays,
so both Arrays will have the same elements even when each is randomly-generated
on reification and each element will be reified just once, regardless of
whether the reification was done by the clone or the original Array.
B<Note:> just as reifying an Array from multiple threads is not safe,
so is, for example, reifying the clone from one thread while reifying
the original from another thread is not safe.

    my @a = 1, {rand} … ∞; my @b = @a.clone;
    say @b[^3]; # OUTPUT: «(1 0.0216426755282736 0.567660896142156)␤»
    say @a[^3]; # OUTPUT: «(1 0.0216426755282736 0.567660896142156)␤»

=head2 method flat

Defined as:

    multi method flat(Array:U:)
    multi method flat(Array:D:)

This method will return the type object itself if it's applied to a type
object; when applied to an object, it will return a C<Seq> created from the
array's underlying iterator.

=for code
my @a = <a 2 c>;
say @a.flat.^name; # OUTPUT: «Seq␤»


=head2 method shift

Defined as:

    method shift(Array:D:) is nodal

Removes and returns the first item from the array.  Fails if the array is empty.

Example:

    my @foo = <a b>;
    say @foo.shift;             # OUTPUT: «a␤»
    say @foo.shift;             # OUTPUT: «b␤»
    say @foo.shift;
    CATCH { default { put .^name, ': ', .Str } };
    # OUTPUT: «X::Cannot::Empty: Cannot shift from an empty Array␤»

=head2 routine unshift

Defined as:

    multi sub    unshift(Array:D, **@values --> Array:D)
    multi method unshift(Array:D: **@values --> Array:D)

Adds the C<@values> to the start of the array, and returns the modified array.
Fails if C<@values> is a lazy list.

Example:

    my @foo = <a b c>;
    @foo.unshift: 1, 3 ... 11;
    say @foo;                   # OUTPUT: «[(1 3 5 7 9 11) a b c]␤»

The notes in L<the documentation for method push|/type/Array#method_push> apply,
regarding how many elements are added to the array.

The L<routine prepend|/type/Array#routine_prepend> is the equivalent for adding multiple elements from one
list or array.

=head2 routine prepend

Defined as

    sub prepend(\array, |elems)
    multi method prepend(Array:D: \values)
    multi method prepend(Array:D: **@values is raw)

Adds the elements from C<LIST> to the front of the array, modifying it
in-place.

Example:

    my @foo = <a b c>;
    @foo.prepend: 1, 3 ... 11;
    say @foo;                   # OUTPUT: «[1 3 5 7 9 11 a b c]␤»

The difference from method C<unshift> is that if you prepend a B<single> array
or list argument, C<prepend> will flatten that array / list, whereas C<unshift>
prepends the list / array as just a single element.

=head2 routine splice

Defined as:

    multi sub    splice(@list,   $start = 0, $elems?, *@replacement --> Array)
    multi method splice(Array:D: $start = 0, $elems?, *@replacement --> Array)

Deletes C<$elems> elements starting from index C<$start> from the C<Array>,
returns them and replaces them by C<@replacement>. If C<$elems> is omitted or
is larger than the number of elements starting from C<$start>,
all the elements starting from index C<$start> are deleted. If both C<$start>
and C<$elems> are omitted, all elements are deleted from the C<Array> and
returned.

Each of C<$start> and C<$elems> can be specified as a
L<Whatever|/type/Whatever> or as a L<Callable|/type/Callable> that returns an
C<Int>-compatible value: this returned value is then used as the
corresponding argument to the C<splice> routine.

A C<Whatever> C<$start> uses the number of elements of C<@list> (or invocant). A
C<Callable> C<$start> is called with one argument—the number of elements in
C<@list> (or C<self>).

A C<Whatever> C<$elems> deletes from C<$start> to end of C<@list> (or C<self>)
(same as no C<$elems>). A C<Callable> C<$elems> is called with one
argument—the number of elements in C<@list> (or C<self>) minus the value
of C<$start>.

Example:

    my @foo = <a b c d e f g>;
    say @foo.splice(2, 3, <M N O P>);        # OUTPUT: «[c d e]␤»
    say @foo;                                # OUTPUT: «[a b M N O P f g]␤»

It can be used to extend an array by simply splicing in more elements than
the current size (since version 6.d)

=for code
my @foo = <a b c d e f g>;
say @foo.splice(6, 4, <M N O P>);       # OUTPUT: «[g]␤»
say @foo;                               # OUTPUT: «[a b c d e f M N O P]␤»

The following equivalences hold (assuming that C«@a.elems ≥ $i»):

=begin code :lang<text>
@a.push($x, $y)      @a.splice: *  , *, $x, $y
@a.pop               @a.splice: *-1,
@a.shift             @a.splice: 0  , 1,
@a.unshift($x, $y)   @a.splice: 0  , 0, $x, $y
@a[$i] = $y          @a.splice: $i , 1, $y,
=end code

As mentioned above, a C«Whatever» or C«Callable» object can be provided
for both the C«$start» and C«$elems» parameters. For example, we could use
either of them to remove the second to last element from an array provided
it's large enough to have one:

    my @foo = <a b c d e f g>;
    say @foo.splice: *-2, *-1;           # OUTPUT: «[f]␤»
    say @foo;                            # OUTPUT: «[a b c d e g]␤»

    my &start     = -> $n { $n - 2 };
    my &elems-num = -> $m { $m - 1 };
    say @foo.splice: &start, &elems-num; # OUTPUT: «[e]␤»
    say @foo;                            # OUTPUT: «[a b c d g]␤»

=head2 method shape

Defined as:

    method shape() { (*,) }

Returns the shape of the array as a list.

Example:

    my @foo[2;3] = ( < 1 2 3 >, < 4 5 6 > ); # Array with fixed dimensions
    say @foo.shape;                          # OUTPUT: «(2 3)␤»
    my @bar = ( < 1 2 3 >, < 4 5 6 > );      # Normal array (of arrays)
    say @bar.shape;                          # OUTPUT: «(*)␤»

=head2 method default

Defined as:

    method default

Returns the default value of the invocant, i.e. the value which is returned when
trying to access an element in the C<Array> which has not been previously
initialized or when accessing an element which has explicitly been set to
C<Nil>. Unless the C<Array> is declared as having a default value by using the
L<is default|/syntax/trait is default> trait the method returns the type object
C<(Any)>.

=begin code
my @a1 = 1, "two", 2.718;
say @a1.default;                               # OUTPUT: «(Any)␤»
say @a1[4];                                    # OUTPUT: «(Any)␤»

my @a2 is default(17) = 1, "two", 3;
say @a2.default;                               # OUTPUT: «17␤»
say @a2[4];                                    # OUTPUT: «17␤»
@a2[1] = Nil;                                  # (resets element to its default)
say @a2[1];                                    # OUTPUT: «17␤»
=end code

=head2 method of

Defined as:

    method of()

Returns the type constraint for the values of the invocant. By default,
i.e. if no type constraint is given during declaration, the method
returns C<(Mu)>.

    my @a1 = 1, 'two', 3.14159;              # (no type constraint specified)
    say @a1.of;                              # OUTPUT: «(Mu)␤»

    my Int @a2 = 1, 2, 3;                    # (values must be of type Int)
    say @a2.of;                              # OUTPUT: «(Int)␤»
    @a2.push: 'd';
    CATCH { default { put .^name, ': ', .Str } };
    # OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to @a2; expected Int but got Str ("d")␤»

=head2 method dynamic

Defined as:

    method dynamic(Array:D: --> Bool:D)

Returns C<True> if the invocant has been declared with the L<is dynamic|/routine/is dynamic>
trait, that is, if it's a dynamic variable that can be accessed from the
inner lexical scope without having been declared there.

    my @a;
    say @a.dynamic;                          # OUTPUT: «False␤»

    my @b is dynamic;
    say @b.dynamic;                          # OUTPUT: «True␤»

If you declare a variable with the C<*> twigil C<is dynamic> is implied.

    my @*b;
    say @*b.dynamic;                         # OUTPUT: «True␤»

Please note that the C<dynamic> trait is a property of the variable, not the
content. If a C<Scalar> dynamic variable contains an array, rules for this
container will apply (and it will always return C<False>).

=head2 method List

Defined as:

    multi method List(Array:D:)

Converts the array to a C<List>

=for code
my @array= [1];
@array[3]=3;
say @array.List;       # OUTPUT: «(1 Nil Nil 3)␤»

The holes will show up as C<Nil>.


=head2 method Slip

Defined as:

     multi method Slip(Array:D: --> Slip:D)

Converts the array to a C<Slip>, filling the holes with the type value the
Array has been defined with.

=for code
my Int @array= [0];
@array[3]=3;
say @array.Slip; # OUTPUT: «(0 (Int) (Int) 3)␤»

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
